﻿using Drive.LiveChat.Model;
using Drive.LiveChat.Server.Models;
using Drive.LiveExcelHost;
using Drive.LiveExcelHost.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Drive.Support.Extensions;
using Microsoft.EntityFrameworkCore.Internal;

namespace Drive.LiveChat.Server.Controllers
{
    class VisitorChatController : Controller
    {

        public void AddVisit(ref long visitorId, int channelId, string url, string refererUrl, string searchengine, string searchkw)
        {
            var visitor = db.Visitors.Find(visitorId);
            if (visitor == null)
            {
                visitor = new Visitor();
                visitor.ip = HttpContext.Current.Request.HostIpAddress;
                db.Visitors.Add(visitor);
                db.SaveChanges();
                visitorId = visitor.Id;
            }
            CreateVisitRecord(visitor.Id, url, refererUrl, searchengine, searchkw);
        }

        public Conversation GetConversation(long visitorId, int channelId, bool isAgent, string content)
        {
            var conv = db.Conversations
                       .OrderBy(x => x.CreateTime).
                       FirstOrDefault(x => x.VisitorId == visitorId && x.ChannelId == channelId);
            if (conv == null || conv.EndTime < DateTime.Now)
            {
                conv = CreateConversation(visitorId, channelId, isAgent, content, conv?.AgentId ?? 0);
            }
            else
            {
                if (isAgent)
                {
                    conv.AgentSendQty = conv.AgentSendQty + 1;
                    conv.AgentLastSendTime = DateTime.Now;
                    conv.UpdateTime = DateTime.Now;
                    conv.LastSendBy = "agent";
                    conv.LastSendContent = content;
                }
                else
                {
                    conv.VisitorSendQty = conv.VisitorSendQty + 1;
                    conv.VisitorLastSendTime = DateTime.Now;
                    conv.UpdateTime = DateTime.Now;
                    conv.LastSendBy = "visitor";
                    conv.LastSendContent = content;
                }
                var ra = db.SaveChanges();
            }
            return conv;
        }

        internal Conversation HandleVisitorMessage(long visitorId, int channelId, bool isAgent, string content, out Model.ChatMessage m)
        {
            var conv = GetConversation(visitorId, channelId, isAgent, content);
            var message = db.ChatMessages.Add(new Model.ChatMessage
            {
                AgentId = 0,
                Content = content,
                ContentType = "text",
                SendBy = "visitor",
                SendTime = DateTime.Now,
                VisitorId = visitorId,
                ConvId = conv.Id
            });
            db.SaveChanges();
            m = message.Entity;
            return conv;
        }

        internal List<Model.ChatMessage> GetMessages(long visitorId, int channelId, int page, int size)
        {
            var convId = db.Conversations.OrderByDescending(x => x.Id)
                .Where(x => x.VisitorId == visitorId && x.ChannelId == channelId)
                .Select(x => x.Id)
                .FirstOrDefault();

            return db.ChatMessages
                .OrderByDescending(x=>x.Id)
                .Where(x => x.ConvId == convId)
                .ToPagedList(page, size)
                .OrderBy(x=>x.Id)
                .ToList();
            // 会话是有渠道的，在不同渠道上的会话消息应该隔离 
            //return db.ChatMessages
            //    .GroupJoin(db.Conversations,x=>x.ConvId,x=>x.Id, (x, y) => new { Table1 = x, Table2 = y.DefaultIfEmpty().FirstOrDefault() })
            //    .OrderByDescending(x => x.Table1.SendTime)
            //    .Where(x => x.Table2 != null)
            //    .Where(x => x.Table2.ChannelId == channelId)
            //    .Where(x => x.Table1 .VisitorId == visitorId)
            //    .Select(x=>x.Table1)
            //    .ToPagedList(page, size);
        }


        /// <summary>
        /// 添加访问记录
        /// </summary>
        public void AddVisit()
        {

        }

        /// <summary>
        /// 客服调度
        /// </summary>
        /// <param name="visitorId"></param>
        public ChatAgent ScheduleAgent(long visitorId, int channelId)
        {
            var conv = db.Conversations
                .OrderByDescending(x => x.CreateTime)
                .FirstOrDefault(x => x.VisitorId == visitorId && x.ChannelId == channelId);
            var lastAgentId = conv?.AgentId ?? 0;
            if (lastAgentId == 0)
            {
                // TODO impl agent schedule core biz.
                // status_online
                // load banlance
                // channel-group rules
                // ...

                lastAgentId = 1;
            }

            var agent = db.ChatAgents.Find(lastAgentId);
            if (RedisAgentStatus.GetIsStatusOnline(lastAgentId))
            {
                return agent;
            }
            else
            {
                //TODO 离线转接
            }
            return agent;
        }

        private Conversation CreateConversation(long visitorId, int channelId, bool isAgent, string content, int lastAgentId = 0)
        {
            var conv = new Conversation();
            conv.VisitorId = visitorId;
            conv.VisitId = 0;
            conv.Ip = Request.HostIpAddress;
            conv.ChannelId = channelId;
            conv.AgentId = lastAgentId;
            conv.CreateTime = DateTime.Now;
            conv.UpdateTime = DateTime.Now;
            conv.LastSendContent = content;
            if (isAgent)
            {
                conv.AgentSendQty = 1;
                conv.AgentLastSendTime = DateTime.Now;
                conv.LastSendBy = "agent";
            }
            else
            {
                conv.VisitorSendQty = 1;
                conv.VisitorLastSendTime = DateTime.Now;
                conv.LastSendBy = "visitor";
            }
            db.Conversations.Add(conv);
            db.SaveChanges();
            return conv;
        }

        private VisitRecord CreateVisitRecord(long visitorId, string url, string refererurl, string searchengine, string searchkw)
        {
            var visit = new VisitRecord();
            visit.VisitorId = visitorId;
            visit.Ip = Request.HostIpAddress;
            visit.Url = url;
            visit.RefererUrl = refererurl;
            visit.SearchEngine = searchengine;
            visit.SearchKeyword = searchkw;
            visit.CreateTime = DateTime.Now;
            db.VisitRecords.Add(visit);
            db.SaveChanges();
            return visit;
        }
    }
}
